

#ifndef SINEANALYZER_DIFF_F_H_
#define SINEANALYZER_DIFF_F_H_
#include "MY_INC/TI_SOLAR/SOLAR_F.h"
#include "math.h"
#include "stdbool.h"
//*********** Structure Definition ********//

/**
 * @brief 定义正弦波分析器的结构体。
 */
typedef struct
{
    // 最终结果
    float32 SampleFreq; // 输入：采样频率（单位：Hz，SampleFreq）
    float32 Threshold;  // 输入：零输入对应的电压阈值（Threshold）
    float32 Vrms;       // 输出：信号的均方根值（RMS，Vrms）
    float32 Vavg;       // 输出：信号的平均值（Vavg）
    float32 Vema;       // 输出：信号的指数移动平均值（EMA，Vema）
    float32 SigFreq;    // 输出：信号的频率（SigFreq）
    Uint8   ZCD : 1;    // 输出：是否检测到过零点（ZCD，1 表示检测到）

    // 内部变量
    float32 Vacc_avg;         // 累积的平均值（用于计算 Vavg）本质上是一个中间变量
    float32 Vacc_rms;         // 累积的平方和值（用于计算 Vrms）本质上是一个中间变量
    float32 Vacc_ema;         // 累积的 EMA 值（用于计算 Vema）本质上是一个中间变量
    float32 curr_sample_norm; // 当前采样值的归一化值（curr_sample_norm）
    Uint8   prev_sign : 1;    // 上一个符号（用于判断过零点，prev_sign）
    Uint8   curr_sign : 1;    // 当前符号（用于判断过零点，curr_sign）
    Uint32  nsamples;         // 半周期内的样本数（nsamples）
    Uint32  nsamplesMin;      // 样本数最小限制（用于过滤异常值，nsamplesMin）
    Uint32  nsamplesMax;      // 样本数最大限制（用于过滤异常值，nsamplesMax）

} SINEANALYZER_DIFF_F;
//*********** Function Declarations *******//

/**
 * @brief 初始化正弦波分析器。
 * @param v 指向正弦波分析器结构体的指针。
 */
static inline void SINEANALYZER_DIFF_F_init(SINEANALYZER_DIFF_F *v, float SampleFreq, float Threshold,
                                            uint32_t nsamplesMin,
                                            uint32_t nsamplesMax) // 初始化结构体（带采样数限制）
{
    // 输入参数
    v->SampleFreq = SampleFreq;   // 输入：信号采样频率（Hz）
    v->nsamplesMin = nsamplesMin; // 内部：周期采样数下限（防噪声干扰）
    v->nsamplesMax = nsamplesMax; // 内部：周期采样数上限（防异常信号）
    v->Threshold = Threshold;     // 输入：零点检测阈值（绝对值低于此值视为负半周）
    // 输出参数
    v->Vrms = 0.0f;    // 输出：电压有效值（RMS）
    v->Vavg = 0.0f;    // 输出：电压平均值（半周期绝对值平均）
    v->Vema = 0.0f;    // 输出：电压指数移动平均值（EMA）
    v->SigFreq = 0.0f; // 输出：信号频率（Hz）
    v->ZCD = 0;        // 输出：零点交叉检测标志（1表示检测到）

    // 内部中间状态变量
    v->prev_sign = 0; // 内部：前一次采样的符号（0负/1正）
    v->curr_sign = 0; // 内部：当前采样的符号（0负/1正）
    v->nsamples = 0;  // 内部：当前周期内的采样数

    // 内部变量
    v->Vacc_avg = 0.0f;         // 累积的平均值（用于计算 Vavg）本质上是一个中间变量
    v->Vacc_rms = 0.0f;         // 累积的平方和值（用于计算 Vrms）本质上是一个中间变量
    v->Vacc_ema = 0.0f;         // 累积的 EMA 值（用于计算 Vema）本质上是一个中间变量
    v->curr_sample_norm = 0.0f; // 当前采样值的归一化值（curr_sample_norm）
}
/**
 * @brief 执行正弦波分析器的核心算法。
 * @param v 指向正弦波分析器结构体的指针。
 */
void SINEANALYZER_DIFF_F_FUNC(SINEANALYZER_DIFF_F *v);

//*********** Macro Definition ***********//
typedef struct
{
    // 最终结果
    float32 SampleFreq; // 输入：采样频率（单位：Hz，SampleFreq）
    float32 Threshold;  // 输入：零输入对应的电压阈值（Threshold）
    float32 Vrms[3];    // 输出：信号的均方根值（RMS，Vrms）
    float32 SigFreq[3]; // 输出：信号的频率（SigFreq）
    // 内部变量
    float32 Vacc_rms[3];         // 累积的平均值（用于计算 Vavg）本质上是一个中间变量
    float32 curr_sample_norm[3]; // 当前采样值的归一化值（curr_sample_norm）
    Uint32  nsamples[3];         // 半周期内的样本数（nsamples）

    Uint8 ZCD_A : 1;       // 输出：是否检测到过零点（ZCD，1 表示检测到）
    Uint8 ZCD_B : 1;       // 输出：是否检测到过零点（ZCD，1 表示检测到）
    Uint8 ZCD_C : 1;       // 输出：是否检测到过零点（ZCD，1 表示检测到）
    Uint8 prev_sign_A : 1; // 上一个符号（用于判断过零点，prev_sign）
    Uint8 prev_sign_B : 1; // 上一个符号（用于判断过零点，prev_sign）
    Uint8 prev_sign_C : 1; // 上一个符号（用于判断过零点，prev_sign）
    Uint8 curr_sign_A : 1; // 当前符号（用于判断过零点，curr_sign）
    Uint8 curr_sign_B : 1; // 当前符号（用于判断过零点，curr_sign）
    Uint8 curr_sign_C : 1; // 当前符号（用于判断过零点，curr_sign）

    Uint32 nsamplesMin; // 样本数最小限制（用于过滤异常值，nsamplesMin）
    Uint32 nsamplesMax; // 样本数最大限制（用于过滤异常值，nsamplesMax）

} ThreePhaseSineAnalyzer_Typedef;
/**
 * @brief 正弦波分析器的核心算法宏定义。
 * @param v 指向正弦波分析器结构体的指针。
 */
static inline void ThreePhaseSineAnalyzer_Init(ThreePhaseSineAnalyzer_Typedef *v, float RmsInit, float SampleFreq,
                                               float Threshold, uint32_t nsamplesMin,
                                               uint32_t nsamplesMax) // 初始化结构体（带采样数限制）
{
    // 输入参数
    v->SampleFreq = SampleFreq;   // 输入：信号采样频率（Hz）
    v->nsamplesMin = nsamplesMin; // 内部：周期采样数下限（防噪声干扰）
    v->nsamplesMax = nsamplesMax; // 内部：周期采样数上限（防异常信号）
    v->Threshold = Threshold;     // 输入：零点检测阈值（绝对值低于此值视为负半周）
    v->Vrms[0] = v->Vrms[1] = v->Vrms[2] = RmsInit;
    // 输出参数

    v->SigFreq[0] = v->SigFreq[1] = v->SigFreq[2] = 0.0f; // 输出：信号频率（Hz）
    v->ZCD_A = v->ZCD_B = v->ZCD_C = 0;                   // 输出：零点交叉检测标志（1表示检测到）

    // 内部中间状态变量
    v->prev_sign_A = v->prev_sign_B = v->prev_sign_C = 0; // 内部：前一次采样的符号（0负/1正）
    v->curr_sign_A = v->curr_sign_B = v->curr_sign_C = 0; // 内部：当前采样的符号（0负/1正）
    v->nsamples[0] = v->nsamples[1] = v->nsamples[2] = 0; // 内部：当前周期内的采样数
    v->Vacc_rms[0] = v->Vacc_rms[1] = v->Vacc_rms[2] = 0.0f;
    v->curr_sample_norm[0] = v->curr_sample_norm[1] = v->curr_sample_norm[2] = 0.0f;
}
static inline void ThreePhaseSineAnalyzer_Inline(ThreePhaseSineAnalyzer_Typedef *v,
                                                 float Ac_Input[3]) // 核心算法宏定义（展开式实现）
{
    float inv_nsamples = 0.0f;
    // 1. 信号预处理：根据阈值判断正/负半周
    v->curr_sample_norm[0] = fabsf(Ac_Input[0]);         // 电压取绝对值（等效整流）
    v->curr_sample_norm[1] = fabsf(Ac_Input[1]);         // 电压取绝对值（等效整流）
    v->curr_sample_norm[2] = fabsf(Ac_Input[2]);         // 电压取绝对值（等效整流）
    v->curr_sign_A = (bool)(Ac_Input[0] > v->Threshold); // 标记当前符号为正
    v->curr_sign_B = (bool)(Ac_Input[1] > v->Threshold); // 标记当前符号为正
    v->curr_sign_C = (bool)(Ac_Input[2] > v->Threshold); // 标记当前符号为正
    // 2. 零点交叉检测（ZCD）
    if ((!v->prev_sign_A) & (v->curr_sign_A))
    {
        // 检测到从负到正的过零（新周期开始）
        v->ZCD_A = 1; // 触发零点交叉标志
        // 3. 计算周期参数
        inv_nsamples = (1.0f) / (++v->nsamples[0]); // // 这里也要进行采样数递增，避免漏掉一个周期，否则会导致数据不准
        // 4. 检查周期长度是否有效（实质上控制了周期长度范围以及噪声）
        v->Vrms[0] = ((v->nsamplesMin < v->nsamples[0]) & (v->nsamples[0] < v->nsamplesMax))
                         ? sqrtf(v->Vacc_rms[0] * inv_nsamples)
                         : 0.0f;

        // 6. 计算信号频率并重置状态
        v->SigFreq[0] = (v->SampleFreq * inv_nsamples); // 计算信号频率（SigFreq）
        v->prev_sign_A = v->curr_sign_A;                // 更新上一个符号
        v->Vacc_rms[0] = 0.0f;                          // 清空累积的平方和值
        v->nsamples[0] = 0.0f;                          // 清空样本数
    }
    else
    {
        v->nsamples[0]++;                                                    // 样本数加 1
        v->Vacc_rms[0] += (v->curr_sample_norm[0] * v->curr_sample_norm[0]); // 累积平方和值
        v->ZCD_A = 0;                                                        // 未检测到过零点，设置 ZCD 为 0
        v->prev_sign_A = v->curr_sign_A;                                     // 更新上一个符号
    }

    if ((!v->prev_sign_B) & (v->curr_sign_B))
    {
        // 检测到从负到正的过零（新周期开始）
        v->ZCD_B = 1; // 触发零点交叉标志
        // 3. 计算周期参数
        inv_nsamples = (1.0f) / (++v->nsamples[1]); // // 这里也要进行采样数递增，避免漏掉一个周期，否则会导致数据不准
        // 4. 检查周期长度是否有效（实质上控制了周期长度范围以及噪声）
        v->Vrms[1] = ((v->nsamplesMin < v->nsamples[1]) & (v->nsamples[1] < v->nsamplesMax))
                         ? sqrtf(v->Vacc_rms[1] * inv_nsamples)
                         : 0.0f;

        // 6. 计算信号频率并重置状态
        v->SigFreq[1] = (v->SampleFreq * inv_nsamples); // 计算信号频率（SigFreq）
        v->prev_sign_B = v->curr_sign_B;                // 更新上一个符号
        v->Vacc_rms[1] = 0.0f;                          // 清空累积的平方和值
        v->nsamples[1] = 0.0f;                          // 清空样本数
    }
    else
    {
        v->nsamples[1]++;                                                    // 样本数加 1
        v->Vacc_rms[1] += (v->curr_sample_norm[1] * v->curr_sample_norm[1]); // 累积平方和值
        v->ZCD_B = 0;                                                        // 未检测到过零点，设置 ZCD 为 0
        v->prev_sign_B = v->curr_sign_B;                                     // 更新上一个符号
    }

    if ((!v->prev_sign_C) & (v->curr_sign_C))
    {
        // 检测到从负到正的过零（新周期开始）
        v->ZCD_C = 1; // 触发零点交叉标志
        // 3. 计算周期参数
        inv_nsamples = (1.0f) / (++v->nsamples[2]); // // 这里也要进行采样数递增，避免漏掉一个周期，否则会导致数据不准
        v->Vrms[2] = ((v->nsamplesMin < v->nsamples[2]) & (v->nsamples[2] < v->nsamplesMax))
                         ? sqrtf(v->Vacc_rms[2] * inv_nsamples)
                         : 0.0f;
        // 6. 计算信号频率并重置状态
        v->SigFreq[2] = (v->SampleFreq * inv_nsamples); // 计算信号频率（SigFreq）
        v->prev_sign_C = v->curr_sign_C;                // 更新上一个符号
        v->Vacc_rms[2] = 0.0f;                          // 清空累积的平方和值
        v->nsamples[2] = 0.0f;                          // 清空样本数
    }
    else
    {
        v->nsamples[2]++;                                                    // 样本数加 1
        v->Vacc_rms[2] += (v->curr_sample_norm[2] * v->curr_sample_norm[2]); // 累积平方和值
        v->ZCD_C = 0;                                                        // 未检测到过零点，设置 ZCD 为 0
        v->prev_sign_C = v->curr_sign_C;                                     // 更新上一个符号
    }
}

/**
 * @brief 正弦波分析器的核心算法宏定义。
 * @param v 指向正弦波分析器结构体的指针。
 */
static inline void SinAnalyzer_RMS_Inline(SINEANALYZER_DIFF_F *v, float Ac_Input) // 核心算法宏定义（展开式实现）
{
    v->curr_sample_norm = fabsf(Ac_Input);          // 电压取绝对值（等效整流）
    v->curr_sign = (Bool)(Ac_Input > v->Threshold); // 标记当前符号为正
    if ((!v->prev_sign) & (v->curr_sign))
    {
        // 检测到从负到正的过零（新周期开始）
        v->ZCD = 1; // 触发零点交叉标志
        // 3. 计算周期参数
        float inv_nsamples =
            (1.0f) / (++v->nsamples); // // 这里也要进行采样数递增，避免漏掉一个周期，否则会导致数据不准
        // 4. 检查周期长度是否有效（实质上控制了周期长度范围以及噪声）
        v->Vrms = ((v->nsamplesMin < v->nsamples) & (v->nsamples < v->nsamplesMax)) ? sqrtf(v->Vacc_rms * inv_nsamples)
                                                                                    : 0.1f; // 防止除0
        // 6. 计算信号频率并重置状态
        v->SigFreq = (v->SampleFreq * inv_nsamples); // 计算信号频率（SigFreq）
        v->prev_sign = v->curr_sign;                 // 更新上一个符号
        v->Vacc_rms = 0.0f;                          // 清空累积的平方和值
        v->nsamples = 0.0f;                          // 清空样本数
    }
    else
    {
        v->nsamples++;                                              // 样本数加 1
        v->Vacc_rms += (v->curr_sample_norm * v->curr_sample_norm); // 累积平方和值
        v->ZCD = 0;                                                 // 未检测到过零点，设置 ZCD 为 0
        v->prev_sign = v->curr_sign;                                // 更新上一个符号
    }
}

#endif /* SINEANALYZER_DIFF_F_H_ */
